namespace VoxelEngine
{
	public class Chunk
	{
		public const int Size = 8;

		public const int BaseTwoSize = 3;

		public const int Mask = 7;

		private readonly World _worldRef;

		private readonly Block[][][] _blocks;

		private readonly short _wx;

		private readonly short _wy;

		private readonly short _wz;

		private ChunkObject _chunkObject;

		public World WorldRef => _worldRef;

		public ChunkObject ChunkObject
		{
			get
			{
				return _chunkObject;
			}
			set
			{
				_chunkObject = value;
				_chunkObject.SetChunk(this);
			}
		}

		public Block this[int lx, int ly, int lz]
		{
			get
			{
				if (lx >= 0 && lx < 8 && ly >= 0 && ly < 8 && lz >= 0 && lz < 8)
				{
					Block block = _blocks[lx][ly][lz];
					if (block == null)
					{
						int num = _wx + lx;
						int num2 = _wy + ly;
						int num3 = _wz + lz;
						int num4 = num + num2 * _worldRef.WorldVisibleSizeX + num3 * _worldRef.WorldVisibleSizeY * _worldRef.WorldVisibleSizeX;
						int num5 = num4 * 2;
						byte type = _worldRef.WorldInBytes[num5];
						Block block2 = new Block((BlockType)type, num, num2, num3);
						block2.Light = _worldRef.WorldInBytes[num5 + 1];
						block = block2;
						_blocks[lx][ly][lz] = block;
					}
					block.Chunk = this;
					return block;
				}
				return _worldRef[_wx + lx, _wy + ly, _wz + lz];
			}
			set
			{
				if (lx < 8 && ly < 8 && lz < 8)
				{
					value.Chunk = this;
					_blocks[lx][ly][lz] = value;
				}
			}
		}

		public Chunk(World world, int x, int y, int z)
		{
			_worldRef = world;
			_blocks = new Block[8][][];
			InitializeBlockArray();
			_wx = (short)(x * 8);
			_wy = (short)(y * 8);
			_wz = (short)(z * 8);
		}

		private void InitializeBlockArray()
		{
			for (int i = 0; i < 8; i++)
			{
				_blocks[i] = new Block[8][];
				for (int j = 0; j < 8; j++)
				{
					_blocks[i][j] = new Block[8];
				}
			}
		}

		public void SetDirty()
		{
			if (_chunkObject != null)
			{
				_chunkObject.SetDirty();
			}
		}

		public void RefreshChunkMesh()
		{
			_chunkObject.ChunkMesh.sharedMesh.Clear();
			_chunkObject.ChunkCollider.sharedMesh.Clear();
			ChunkRenderer.Render(this, _chunkObject);
		}
	}
}
